package dnl.jexem.camouflaj;

import java.io.File;
import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This agent runs on a machine while checking for commands left for it in its
 * configured remote location. If it finds a new command it will execute it and
 * return the result.
 * 
 * @author Daniel Orr
 * 
 */
public class Agent extends Thread {

	private static final Logger logger = LoggerFactory.getLogger(Agent.class.getSimpleName());

	/*
	 * When the agent gets commands it will sleep for this period for new
	 * commands retrieval.
	 */
	private static final long ACTIVE_SLEEP_PERIOD = 10 * 1000;

	private static final long PASSIVE_SLEEP_PERIOD = 60 * 1000;

	private long sleepInterval = ACTIVE_SLEEP_PERIOD;

	private boolean active;

	private RemoteCommandManager commandManager;

	public Agent(RemoteCommandManager commandManager) {
		this.commandManager = commandManager;
	}

	@Override
	public void run() {
		// counts the times the command was not executed.
		int unExecCount = 0;
		while (true) {
			boolean commandExecuted = commandManager.executeCommands();
			// we keep track of wether the command was executed or not.
			if (commandExecuted) {
				unExecCount = 0;
				setActive(true);
			} else {
				unExecCount++;
			}
			// if there was no activity for a while
			if (unExecCount > 9) {
				setActive(false);
			}
			try {
				Thread.sleep(sleepInterval);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	private void setActive(boolean active) {
		if (!this.active && active) {
			logger.info("Moving into active state.");
			sleepInterval = ACTIVE_SLEEP_PERIOD;
		} else if (this.active && !active) {
			logger.info("Moving into passive state.");
			// sleep for longer periods
			sleepInterval = PASSIVE_SLEEP_PERIOD;
		}
		this.active = active;
	}

	public static void main(String[] args) {

		String propsFileName = "camouflaj.properties";
		if (args.length == 1) {
			propsFileName = args[0];
		} else if (args.length > 1) {
			printUsageAndExit();
		}
		File propsFile = new File(propsFileName);
		if (!propsFile.exists()) {
			System.err.println("Could not find " + propsFileName);
			System.exit(1);
		}

		RemoteCommandManager remoteCommandManager = null;
		try {
			Config config = new Config(propsFile);
			remoteCommandManager = config.getRemoteCommandManager();
		} catch (IOException e) {
			handleException(e);
		}

		Agent agent = new Agent(remoteCommandManager);
		agent.start();
	}

	private static void printUsageAndExit() {
		System.err.println("Usage: Agent [propertiesFile]");
		System.exit(1);
	}

	private static void handleException(Exception e) {
		System.err.println("Error: " + e.getMessage());
		System.exit(1);
	}
}
